home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / src / sysdep.cc < prev    next >
C/C++ Source or Header  |  1997-07-10  |  14KB  |  736 lines

  1. /*
  2.  
  3. Copyright (C) 1996 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Octave; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. */
  22.  
  23. /*
  24.  
  25. The function gethostname was adapted from a similar function from GNU
  26. Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991 Free
  27. Software Foundation, Inc.
  28.  
  29. */
  30.  
  31. /* Modified by Klaus Gebhardt, 1996 */
  32.  
  33. #ifdef HAVE_CONFIG_H
  34. #include <config.h>
  35. #endif
  36.  
  37. #include <cfloat>
  38. #include <cstddef>
  39. #include <cstdio>
  40. #include <cstdlib>
  41. #include <cstring>
  42.  
  43. #include <string>
  44.  
  45. #include <iostream.h>
  46.  
  47. #ifdef HAVE_UNISTD_H
  48. #ifdef HAVE_SYS_TYPES_H
  49. #include <sys/types.h>
  50. #endif
  51. #include <unistd.h>
  52. #endif
  53.  
  54. #if defined (HAVE_TERMIOS_H)
  55. #include <termios.h>
  56. #elif defined (HAVE_TERMIO_H)
  57. #include <termio.h>
  58. #elif defined (HAVE_SGTTY_H)
  59. #include <sgtty.h>
  60. #else
  61. LOSE! LOSE!
  62. #endif
  63.  
  64. #ifdef __EMX__
  65. #include <float.h>
  66. #include <sys/uflags.h>
  67. #endif
  68.  
  69. #if defined (HAVE_FLOATINGPOINT_H)
  70. #include <floatingpoint.h>
  71. #endif
  72.  
  73. #if defined (HAVE_IEEEFP_H)
  74. #include <ieeefp.h>
  75. #endif
  76.  
  77. #if !defined (HAVE_GETHOSTNAME) && defined (HAVE_SYS_UTSNAME_H)
  78. #include <sys/utsname.h>
  79. #endif
  80.  
  81. #ifndef __EMX__
  82. #if defined (USE_READLINE)
  83. #include <readline/readline.h>
  84. #include <readline/tilde.h>
  85. #endif
  86. extern char *term_clrpag;
  87. extern "C" void _rl_output_character_function ();
  88. #else
  89. #include <readline/readline.h>
  90. #include <readline/tilde.h>
  91. #include <sys/ioctl.h>
  92. extern "C"
  93. {
  94.   extern void tputs ();
  95.   extern char *term_clrpag;
  96.   extern void _rl_output_character_function ();
  97. }
  98. #endif
  99.  
  100. #include "mach-info.h"
  101. #include "oct-math.h"
  102.  
  103. #include "defun.h"
  104. #include "error.h"
  105. #include "help.h"
  106. #include "input.h"
  107. #include "mappers.h"
  108. #include "oct-obj.h"
  109. #include "pager.h"
  110. #include "pathlen.h"
  111. #include "ov.h"
  112. #include "sysdep.h"
  113. #include "toplev.h"
  114. #include "utils.h"
  115.  
  116. #ifndef STDIN_FILENO
  117. #define STDIN_FILENO 1
  118. #endif
  119.  
  120. #if defined (__386BSD__) || defined (__FreeBSD__)
  121. static void
  122. BSD_init (void)
  123. {
  124. #if defined (HAVE_FLOATINGPOINT_H)
  125.   // Disable trapping on common exceptions.
  126.   fpsetmask (~(FP_X_OFL|FP_X_INV|FP_X_DZ|FP_X_DNML|FP_X_UFL|FP_X_IMP));
  127. #endif
  128. }
  129. #endif
  130.  
  131. #if defined (NeXT)
  132. extern "C"
  133. {
  134.   typedef void (*_cplus_fcn_int) (int);
  135.   extern void (*malloc_error (_cplus_fcn_int)) (int);
  136. }
  137.  
  138. static void
  139. malloc_handler (int code)
  140. {
  141.   if (code == 5)
  142.     warning ("hopefully recoverable malloc error: freeing wild pointer");
  143.   else
  144.     {
  145.       panic ("probably irrecoverable malloc error: code %d", code);
  146.     }
  147. }
  148.  
  149. static void
  150. NeXT_init (void)
  151. {
  152.   malloc_error (malloc_handler);
  153. }
  154. #endif
  155.  
  156. #if defined (__EMX__)
  157. OS2_init (void)
  158. {
  159.   _control87 ((EM_INVALID | EM_DENORMAL | EM_ZERODIVIDE | EM_OVERFLOW
  160.            | EM_UNDERFLOW | EM_INEXACT), MCW_EM);
  161.  
  162.   _uflags (_UF_SBRK_MODEL, _UF_SBRK_ARBITRARY);
  163. }
  164. #endif
  165.  
  166. #if defined (SCO)
  167. static void
  168. SCO_init (void)
  169. {
  170. #if defined (HAVE_IEEEFP_H)
  171.   // Disable trapping on common exceptions.
  172.   fpsetmask (~(FP_X_OFL|FP_X_INV|FP_X_DZ|FP_X_DNML|FP_X_UFL|FP_X_IMP));
  173. #endif
  174. }
  175. #endif
  176.  
  177. void
  178. sysdep_init (void)
  179. {
  180. #if defined (__386BSD__) || defined (__FreeBSD__)
  181.   BSD_init ();
  182. #elif defined (NeXT)
  183.   NeXT_init ();
  184. #elif defined (__EMX__)
  185.   OS2_init ();
  186. #elif defined (SCO)
  187.   SCO_init ();
  188. #endif
  189.  
  190.   octave_ieee_init ();
  191. }
  192.  
  193. // Set terminal in raw mode.  From less-177.
  194. //
  195. // Change terminal to "raw mode", or restore to "normal" mode.
  196. // "Raw mode" means 
  197. //    1. An outstanding read will complete on receipt of a single keystroke.
  198. //    2. Input is not echoed.  
  199. //    3. On output, \n is mapped to \r\n.
  200. //    4. \t is NOT expanded into spaces.
  201. //    5. Signal-causing characters such as ctrl-C (interrupt),
  202. //       etc. are NOT disabled.
  203. // It doesn't matter whether an input \n is mapped to \r, or vice versa.
  204.  
  205. void
  206. raw_mode (int on)
  207. {
  208.   static int curr_on = 0;
  209.  
  210.   int tty_fd = STDIN_FILENO;
  211.   if (! isatty (tty_fd))
  212.     {
  213.       if (interactive)
  214.     error ("stdin is not a tty!");
  215.       return;
  216.     }
  217.  
  218.   if (on == curr_on)
  219.     return;
  220.  
  221. #if defined (HAVE_TERMIOS_H)
  222.   {
  223.     struct termios s;
  224.     static struct termios save_term;
  225.  
  226.     if (on)
  227.       {
  228.     // Get terminal modes.
  229.  
  230.     tcgetattr (tty_fd, &s);
  231.  
  232.     // Save modes and set certain variables dependent on modes.
  233.  
  234.     save_term = s;
  235. //    ospeed = s.c_cflag & CBAUD;
  236. //    erase_char = s.c_cc[VERASE];
  237. //    kill_char = s.c_cc[VKILL];
  238.  
  239.     // Set the modes to the way we want them.
  240.  
  241.     s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
  242.     s.c_oflag |=  (OPOST|ONLCR);
  243. #if defined (OCRNL)
  244.     s.c_oflag &= ~(OCRNL);
  245. #endif
  246. #if defined (ONOCR)
  247.     s.c_oflag &= ~(ONOCR);
  248. #endif
  249. #if defined (ONLRET)
  250.     s.c_oflag &= ~(ONLRET);
  251. #endif
  252.     s.c_cc[VMIN] = 1;
  253.     s.c_cc[VTIME] = 0;
  254.       }      
  255.     else
  256.       {
  257.     // Restore saved modes.
  258.  
  259.     s = save_term;
  260.       }
  261.     tcsetattr (tty_fd, TCSAFLUSH, &s);
  262.   }
  263. #elif defined (HAVE_TERMIO_H)
  264.   {
  265.     struct termio s;
  266.     static struct termio save_term;
  267.  
  268.     if (on)
  269.       {
  270.     // Get terminal modes.
  271.  
  272.     ioctl (tty_fd, TCGETA, &s);
  273.  
  274.     // Save modes and set certain variables dependent on modes.
  275.  
  276.     save_term = s;
  277. //    ospeed = s.c_cflag & CBAUD;
  278. //    erase_char = s.c_cc[VERASE];
  279. //    kill_char = s.c_cc[VKILL];
  280.  
  281.     // Set the modes to the way we want them.
  282.  
  283.     s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
  284.     s.c_oflag |=  (OPOST|ONLCR);
  285. #if defined (OCRNL)
  286.     s.c_oflag &= ~(OCRNL);
  287. #endif
  288. #if defined (ONOCR)
  289.     s.c_oflag &= ~(ONOCR);
  290. #endif
  291. #if defined (ONLRET)
  292.     s.c_oflag &= ~(ONLRET);
  293. #endif
  294.     s.c_cc[VMIN] = 1;
  295.     s.c_cc[VTIME] = 0;
  296.       }      
  297.     else
  298.       {
  299.     // Restore saved modes.
  300.  
  301.     s = save_term;
  302.       }
  303.     ioctl (tty_fd, TCSETAW, &s);
  304.   }
  305. #elif defined (HAVE_SGTTY_H)
  306.   {
  307.     struct sgttyb s;
  308.     static struct sgttyb save_term;
  309.  
  310.     if (on)
  311.       {
  312.     // Get terminal modes.
  313.  
  314.     ioctl (tty_fd, TIOCGETP, &s);
  315.  
  316.     // Save modes and set certain variables dependent on modes.
  317.  
  318.     save_term = s;
  319. //    ospeed = s.sg_ospeed;
  320. //    erase_char = s.sg_erase;
  321. //    kill_char = s.sg_kill;
  322.  
  323.     // Set the modes to the way we want them.
  324.  
  325.     s.sg_flags |= CBREAK;
  326.     s.sg_flags &= ~(ECHO);
  327.       } 
  328.     else
  329.       {
  330.     // Restore saved modes.
  331.  
  332.     s = save_term;
  333.       }
  334.     ioctl (tty_fd, TIOCSETN, &s);
  335.   }
  336. #else
  337. LOSE! LOSE!
  338. #endif
  339.  
  340.   curr_on = on;
  341. }
  342.  
  343. // Read one character from the terminal.
  344.  
  345. int
  346. kbhit (void)
  347. {
  348.   int c;
  349.   flush_octave_stdout ();
  350.   raw_mode (1);
  351.   c = cin.get ();
  352.   raw_mode (0);
  353.   return c;
  354. }
  355.  
  356. string
  357. octave_getcwd (void)
  358. {
  359.   string retval;
  360.  
  361.   char buf[MAXPATHLEN];
  362.  
  363.   char *tmp = 0;
  364.  
  365. #if defined (__EMX__)
  366.   tmp = _getcwd2 (buf, MAXPATHLEN);
  367. #elif defined (HAVE_GETWD)
  368.   tmp = getwd (buf);
  369. #elif defined (HAVE_GETCWD)
  370.   tmp = getwd (buf, MAXPATHLEN);
  371. #endif
  372.  
  373.   if (tmp)
  374.     retval = tmp;
  375.   else
  376.     error ("unable to find current directory");
  377.  
  378.   return retval;
  379. }
  380.  
  381. int
  382. octave_chdir (const string& path)
  383. {
  384. #if defined (__EMX__)
  385.   int retval = -1;
  386.  
  387.   char *tmp_path = strsave (path.c_str ());
  388.  
  389.   if (path.length () == 2 && path[1] == ':')
  390.     {
  391.       char *upper_case_dir_name = strupr (tmp_path);
  392.       _chdrive (upper_case_dir_name[0]);
  393.       if (_getdrive () == upper_case_dir_name[0])
  394.     retval = _chdir2 ("/");
  395.     }
  396.   else
  397.     retval = _chdir2 (tmp_path);
  398.  
  399.   delete [] tmp_path;
  400.  
  401.   return retval;
  402. #else
  403.   return chdir (path.c_str ());
  404. #endif
  405. }
  406.  
  407. DEFUN (clc, , ,
  408.   "clc (): clear screen")
  409. {
  410.   octave_value_list retval;
  411.  
  412.   rl_beg_of_line ();
  413.   rl_kill_line (1);
  414.  
  415. #if ! defined (_GO32_)
  416.   if (term_clrpag)
  417.     tputs (term_clrpag, 1, _rl_output_character_function);
  418.   else
  419.     crlf ();
  420. #else
  421.   crlf ();
  422. #endif
  423.  
  424.   fflush (rl_outstream);
  425.  
  426.   return retval;
  427. }
  428.  
  429. DEFALIAS (home, clc);
  430.  
  431. DEFUN (getenv, args, ,
  432.   "getenv (STRING): get environment variable values")
  433. {
  434.   octave_value_list retval;
  435.  
  436.   int nargin = args.length ();
  437.  
  438.   if (nargin == 1)
  439.     {
  440.       string tstr = args(0).string_value ();
  441.       const char *name = tstr.c_str ();
  442.  
  443.       if (! error_state)
  444.     {
  445.       char *value = getenv (name);
  446.       if (value)
  447.         retval = value;
  448.       else
  449.         retval = "";
  450.     }
  451.     }
  452.   else
  453.     print_usage ("getenv");
  454.  
  455.   return retval;
  456. }
  457.  
  458. DEFUN (putenv, args, ,
  459.   "putenv (VAR, VALUE): define environment variable VAR=VALUE")
  460. {
  461.   octave_value_list retval;
  462.  
  463.   int nargin = args.length ();
  464.  
  465.   if (nargin == 2)
  466.     {
  467.       string var = args(0).string_value (); 
  468.  
  469.       if (! error_state)
  470.     {
  471.       string val = args(1).string_value (); 
  472.  
  473.       if (! error_state)
  474.         oct_putenv (var.c_str (), val.c_str ());
  475.       else
  476.         error ("putenv: second argument should be a string");
  477.     }
  478.       else
  479.     error ("putenv: first argument should be a string");
  480.     }
  481.   else
  482.     print_usage ("putenv");
  483.  
  484.   return retval;
  485. }
  486.  
  487. DEFUN (kbhit, , ,
  488.   "kbhit: get a single character from the terminal")
  489. {
  490.   octave_value_list retval;
  491.  
  492.   // XXX FIXME XXX -- add timeout and default value args?
  493.  
  494.   if (interactive || really_forced_interactive)
  495.     {
  496.       int c = kbhit ();
  497.       char *s = new char [2];
  498.       s[0] = c;
  499.       s[1] = '\0';
  500.       retval = s;
  501.     }
  502.  
  503.   return retval;
  504. }
  505.  
  506. DEFUN (pause, args, ,
  507.   "pause (seconds): suspend program execution")
  508. {
  509.   octave_value_list retval;
  510.  
  511.   int nargin = args.length ();
  512.  
  513.   if (! (nargin == 0 || nargin == 1))
  514.     {
  515.       print_usage ("pause");
  516.       return retval;
  517.     }
  518.  
  519.   if (nargin == 1)
  520.     {
  521.       double dval = args(0).double_value ();
  522.  
  523.       if (! error_state)
  524.     {
  525.       if (xisnan (dval))
  526.         warning ("pause: NaN is an invalid delay");
  527.       else if (xisinf (dval))
  528.         kbhit ();
  529.       else
  530.         {
  531.           int delay = NINT (dval);
  532.           if (delay > 0)
  533.         sleep (delay);
  534.         }
  535.     }
  536.     }
  537.   else
  538.     kbhit ();
  539.  
  540.   return retval;
  541. }
  542.  
  543. DEFUN (sleep, args, ,
  544.   "sleep (seconds): suspend program execution")
  545. {
  546.   octave_value_list retval;
  547.  
  548.   if (args.length () == 1)
  549.     {
  550.       double dval = args(0).double_value ();
  551.  
  552.       if (! error_state)
  553.     {
  554.       if (xisnan (dval))
  555.         warning ("sleep: NaN is an invalid delay");
  556.       else
  557.         {
  558.           int delay = NINT (dval);
  559.           if (delay > 0)
  560.         sleep (delay);
  561.         }
  562.     }
  563.     }
  564.   else
  565.     print_usage ("sleep");
  566.  
  567.   return retval;
  568. }
  569.  
  570. DEFUN (usleep, args, ,
  571.   "usleep (microseconds): suspend program execution")
  572. {
  573.   octave_value_list retval;
  574.  
  575.   if (args.length () == 1)
  576.     {
  577.       double dval = args(0).double_value ();
  578.  
  579.       if (! error_state)
  580.     {
  581.       if (xisnan (dval))
  582.         warning ("usleep: NaN is an invalid delay");
  583.       else
  584.         {
  585. #if defined (HAVE_USLEEP)
  586.           int delay = NINT (dval);
  587.  
  588.           if (delay > 0)
  589.         usleep (delay);
  590. #elif defined (HAVE__SLEEP2)
  591.           int delay = NINT (dval / 1e3);
  592.  
  593.           if (delay > 0)
  594.         _sleep2 (delay);
  595. #else
  596.           int delay = NINT (dval / 1e6);
  597.  
  598.           if (delay > 0)
  599.         sleep (delay);
  600. #endif
  601.         }
  602.     }
  603.     }
  604.   else
  605.     print_usage ("usleep");
  606.  
  607.   return retval;
  608. }
  609.  
  610. // XXX FIXME XXX -- maybe this should only return 1 if IEEE floating
  611. // point functions really work.
  612.  
  613. DEFUN (isieee, , ,
  614.   "isieee (): return 1 if host uses IEEE floating point")
  615. {
  616.   oct_mach_info::float_format flt_fmt =
  617.     oct_mach_info::native_float_format ();
  618.  
  619.   return (double) (flt_fmt == oct_mach_info::ieee_little_endian
  620.            || flt_fmt == oct_mach_info::ieee_big_endian);
  621. }
  622.  
  623. #if !defined (HAVE_GETHOSTNAME) && defined (HAVE_SYS_UTSNAME_H)
  624. int
  625. gethostname (char *name, int namelen)
  626. {
  627.   int i;
  628.   struct utsname ut;
  629.  
  630.   --namelen;
  631.  
  632.   uname (&ut);
  633.   i = strlen (ut.nodename) + 1;
  634.   strncpy (name, ut.nodename, i < namelen ? i : namelen);
  635.   name[namelen] = '\0';
  636.  
  637.   return 0;
  638. }
  639. #endif
  640.  
  641. // The check for error state allows us to do this:
  642. //
  643. //   string foo = oct_tilde_expand (args(0).string_value ());
  644. //
  645. // without having to use a temporary and check error_state before
  646. // calling oct_tilde_expand.
  647.  
  648. string
  649. oct_tilde_expand (const string& name)
  650. {
  651.   string retval;
  652.  
  653.   if (! error_state)
  654.     {
  655.       char *tmp = tilde_expand (name.c_str ());
  656.       retval = tmp;
  657.       delete [] tmp;
  658.     }
  659.  
  660.   return retval;
  661. }
  662.  
  663. // A vector version of the above.
  664.  
  665. string_vector
  666. oct_tilde_expand (const string_vector& names)
  667. {
  668.   string_vector retval;
  669.  
  670.   if (! error_state)
  671.     {
  672.       int n = names.length ();
  673.  
  674.       retval.resize (n);
  675.  
  676.       for (int i = 0; i < n; i++)
  677.     retval[i] = oct_tilde_expand (names[i]);
  678.     }
  679.  
  680.   return retval;
  681. }
  682.  
  683. DEFUN (tilde_expand, args, ,
  684.   "tilde_expand (STRING): perform tilde expansion on STRING")
  685. {
  686.   octave_value_list retval;
  687.  
  688.   int nargin = args.length ();
  689.  
  690.   if (nargin == 1)
  691.     retval = oct_tilde_expand (args(0).all_strings ());
  692.   else
  693.     print_usage ("tilde_expand");
  694.  
  695.   return retval;
  696. }
  697.  
  698. #if defined (__EMX__) && defined (OS2)
  699.  
  700. DEFUN_TEXT (extproc, , ,
  701.   "extproc : ignored by Octave")
  702. {
  703.   return octave_value_list ();
  704. }
  705.  
  706. DEFALIAS (EXTPROC, extproc);
  707.  
  708. DEFUN (add_to_command_number, args, ,
  709.        "add_to_command_number: add argument to the current command number")
  710. {
  711.   octave_value_list retval;
  712.   int nargin;
  713.  
  714.   if ((nargin = args.length ()) != 1)
  715.     {
  716.       print_usage ("add_to_command_number");
  717.       return retval;
  718.     }
  719.  
  720.   double tmp_d = args(0).double_value ();
  721.  
  722.   if (error_state || ((int) tmp_d != tmp_d))
  723.     error ("add_to_command_number: expecting integer as argument");
  724.   else
  725.     current_command_number += (int) tmp_d;
  726.  
  727.   return retval;
  728. }
  729. #endif
  730.  
  731. /*
  732. ;;; Local Variables: ***
  733. ;;; mode: C++ ***
  734. ;;; End: ***
  735. */
  736.